<!DOCTYPE html>

<html lang="en">
  <head>
    
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Tutorial 4: Using CRUDs &mdash; Phalcon 2.0.0 文档</title>
    <meta name="keywords" content="php, phalcon, phalcon php, php framework, faster php framework"><link rel="stylesheet" type="text/css" href="../_static/bootstrap.min.css" />
    <link rel="stylesheet" type="text/css" href="http://static.phalconphp.com/css/phalcon.min.css" />
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:700,400' rel='stylesheet' type='text/css'>
    <link href="http://fonts.googleapis.com/css?family=Merriweather:400,700" rel="stylesheet" type="text/css" />
    <!--
    EUROPE <link href='https://fonts.googleapis.com/css?family=Open+Sans:700,400&subset=latin-ext' rel='stylesheet' type='text/css'>
    GREEK <link href='https://fonts.googleapis.com/css?family=Open+Sans:700,400&subset=greek-ext' rel='stylesheet' type='text/css'>
    RUSSIA <link href='https://fonts.googleapis.com/css?family=Open+Sans:700,400&subset=cyrillic-ext,latin' rel='stylesheet' type='text/css'>
    -->

    <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
      <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <link rel="stylesheet" href="../_static/docs.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '2.0.0',
        COLLAPSE_MODINDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>

    <script src="../_static/jquery.min.js"></script>
    <script type="text/javascript" src="../_static/docs.js"></script>
    <link rel="shortcut icon" href="../_static/favicon.ico"/>
    <link rel="top" title="Phalcon 2.0.0 文档" href="../index.html" />
    <link rel="next" title="Tutorial 5: Customizing INVO" href="tutorial-invo-4.html" />
    <link rel="prev" title="Tutorial 3: Securing INVO" href="tutorial-invo-2.html" /> 
  </head>
  <body>

<header class="page-header">
    <nav class="navbar" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#main-menu-container">
                    <span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span>
                </button>
                <a class="navbar-brand phalcon-logo" href="/"><span itemprop="name" class="sr-only">Phalcon PHP</span></a>
            </div>

            <div class="collapse navbar-collapse navbar-right" id="main-menu-container">
                <ul class="nav navbar-nav main-menu">
                  <li class="first"><a href="http://phalconphp.com/en/download" class="header-nav-link">Download</a></li>
                  <li><a href="http://docs.phalconphp.com/en/latest/index.html" class="header-nav-link" target="_blank">Documentation</a></li>
                  <li><a href="http://forum.phalconphp.com/" class="header-nav-link" target="_blank">Forum</a></li>
                  <li><a href="http://blog.phalconphp.com/" class="header-nav-link" target="_blank">Blog</a></li>
                  <li><a href="http://phalconphp.com/en/about">About</a></li>
                </ul>
            </div>
        </div>
    </nav>
  </header>

<div class="heading">
    <div class="container">
        <div class="row">
            <h2>Documentation</h2>
        </div>
    </div>
</div>
    <!--<div class="header-line">
      <div class="size-wrap">
        <div class="header-line-title title-white">Documentation</div>
      </div>
    </div>-->
    <div class="related">
      <ul>
        <li class="right" >
          <a href="../genindex.html" title="总目录"
             accesskey="I">索引</a></li>
        <li class="right" >
          <a href="tutorial-invo-4.html" title="Tutorial 5: Customizing INVO"
             accesskey="N">下一页</a> |</li>
        <li class="right" >
          <a href="tutorial-invo-2.html" title="Tutorial 3: Securing INVO"
             accesskey="P">上一页</a> |</li>
        <li><a href="http://phalconphp.com">Home</a> &raquo;</li>
        <li><a href="../index.html">Phalcon 2.0.0 文档</a> &raquo;</li> 
      </ul>
    </div>  

      <table width="100%" align="center" cellpadding="0" cellspacing="0">
        <tr>
      <td class="primary-box" width="25%" valign="top">
            <div>
            <div id="searchbox" style="">
                <!--<form class="search" action="http://readthedocs.org/search/project/" method="get">
                  <input type="search" name="q" size="25" placeholder="Search">
                  <input type="submit" value="Go">
                  <input type="hidden" name="selected_facets" value="project:">
                </form>-->
                <div style="width:200px;padding:10px">
                  <gcse:searchbox-only></gcse:searchbox-only>
                </div>
            </div>
            </div>
            <div style="padding:5px;padding-left:10px">
              <div id="carbonads-container">
                <div class="carbonad"><div id="azcarbon"></div>
                <script type="text/javascript">var z = document.createElement("script"); z.type = "text/javascript"; z.async = true; z.src = "http://engine.carbonads.com/z/56496/azcarbon_2_1_0_VERT"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(z, s);</script>
                </div></div>
            </div>
            <h3><a href="../index.html">內容目录</a></h3>
            <ul>
<li><a class="reference internal" href="#">Tutorial 4: Using CRUDs</a><ul>
<li><a class="reference internal" href="#working-with-the-crud">Working with the CRUD</a><ul>
<li><a class="reference internal" href="#the-search-form">The Search Form</a></li>
<li><a class="reference internal" href="#performing-a-search">Performing a Search</a></li>
<li><a class="reference internal" href="#creating-and-updating-records">Creating and Updating Records</a></li>
</ul>
</li>
</ul>
</li>
</ul>

            <h4>上一个主题</h4>
            <p class="topless"><a href="tutorial-invo-2.html" title="上一章">&lt; Tutorial 3: Securing INVO</a></p>
            <h4>下一个主题</h4>
            <p class="topless"><a href="tutorial-invo-4.html" title="下一章">Tutorial 5: Customizing INVO &gt;</a></p>
            <h3>本页</h3>
            <ul class="this-page-menu">
              <li><a href="../_sources/reference/tutorial-invo-3.txt" rel="nofollow">显示源代码</a></li>
            </ul>
        </td>
          <td class="second-box" valign="top">
            <div class="document">
                <div class="documentwrapper">
                  <div class="bodywrapper">
                    <div class="body" >
                      
  <div class="section" id="tutorial-4-using-cruds">
<h1>Tutorial 4: Using CRUDs<a class="headerlink" href="#tutorial-4-using-cruds" title="永久链接至标题">¶</a></h1>
<p>Backends usually provides forms to allow users to manipulate data. Continuing the explanation of
INVO, we now address the creation of CRUDs, a very common task that Phalcon will facilitate you
using forms, validations, paginators and more.</p>
<div class="section" id="working-with-the-crud">
<h2>Working with the CRUD<a class="headerlink" href="#working-with-the-crud" title="永久链接至标题">¶</a></h2>
<p>Most options that manipulate data in INVO (companies, products and types of products), were developed
using a basic and common <a class="reference external" href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> (Create, Read, Update and Delete). Each CRUD contains the following files:</p>
<div class="highlight-bash"><div class="highlight"><pre>invo/
    app/
        controllers/
            ProductsController.php
        models/
            Products.php
        forms/
            ProductsForm.php
        views/
            products/
                edit.volt
                index.volt
                new.volt
                search.volt
</pre></div>
</div>
<p>Each controller has the following actions:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="k">class</span> <span class="nc">ProductsController</span> <span class="k">extends</span> <span class="nx">ControllerBase</span>
<span class="p">{</span>

    <span class="sd">/**</span>
<span class="sd">     * The start action, it shows the &quot;search&quot; view</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">indexAction</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">//...</span>
    <span class="p">}</span>

    <span class="sd">/**</span>
<span class="sd">     * Execute the &quot;search&quot; based on the criteria sent from the &quot;index&quot;</span>
<span class="sd">     * Returning a paginator for the results</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">searchAction</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">//...</span>
    <span class="p">}</span>

    <span class="sd">/**</span>
<span class="sd">     * Shows the view to create a &quot;new&quot; product</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">newAction</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">//...</span>
    <span class="p">}</span>

    <span class="sd">/**</span>
<span class="sd">     * Shows the view to &quot;edit&quot; an existing product</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">editAction</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">//...</span>
    <span class="p">}</span>

    <span class="sd">/**</span>
<span class="sd">     * Creates a product based on the data entered in the &quot;new&quot; action</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">createAction</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">//...</span>
    <span class="p">}</span>

    <span class="sd">/**</span>
<span class="sd">     * Updates a product based on the data entered in the &quot;edit&quot; action</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">saveAction</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="c1">//...</span>
    <span class="p">}</span>

    <span class="sd">/**</span>
<span class="sd">     * Deletes an existing product</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">deleteAction</span><span class="p">(</span><span class="nv">$id</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="c1">//...</span>
    <span class="p">}</span>

<span class="p">}</span>
</pre></div>
</div>
<div class="section" id="the-search-form">
<h3>The Search Form<a class="headerlink" href="#the-search-form" title="永久链接至标题">¶</a></h3>
<p>Every CRUD starts with a search form. This form shows each field that has the table (products), allowing the user
to create a search criteria from any field. Table &#8220;products&#8221; has a relationship to the table &#8220;products_types&#8221;.
In this case, we previously queried the records in this table in order to facilitate the search by that field:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="sd">/**</span>
<span class="sd"> * The start action, it shows the &quot;search&quot; view</span>
<span class="sd"> */</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">indexAction</span><span class="p">()</span>
<span class="p">{</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">persistent</span><span class="o">-&gt;</span><span class="na">searchParams</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">view</span><span class="o">-&gt;</span><span class="na">form</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ProductsForm</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>An instance of the form ProductsForm (app/forms/ProductsForm.php) is passed to the view.
This form defines the fields that are visible to the user:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="k">use</span> <span class="nx">Phalcon\Forms\Form</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Phalcon\Forms\Element\Text</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Phalcon\Forms\Element\Hidden</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Phalcon\Forms\Element\Select</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Phalcon\Validation\Validator\Email</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Phalcon\Validation\Validator\PresenceOf</span><span class="p">;</span>
<span class="k">use</span> <span class="nx">Phalcon\Validation\Validator\Numericality</span><span class="p">;</span>

<span class="k">class</span> <span class="nc">ProductsForm</span> <span class="k">extends</span> <span class="nx">Form</span>
<span class="p">{</span>

    <span class="sd">/**</span>
<span class="sd">     * Initialize the products form</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">initialize</span><span class="p">(</span><span class="nv">$entity</span> <span class="o">=</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">array</span><span class="p">())</span>
    <span class="p">{</span>

        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">isset</span><span class="p">(</span><span class="nv">$options</span><span class="p">[</span><span class="s1">&#39;edit&#39;</span><span class="p">]))</span> <span class="p">{</span>
            <span class="nv">$element</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Text</span><span class="p">(</span><span class="s2">&quot;id&quot;</span><span class="p">);</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$element</span><span class="o">-&gt;</span><span class="na">setLabel</span><span class="p">(</span><span class="s2">&quot;Id&quot;</span><span class="p">));</span>
        <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="k">new</span> <span class="nx">Hidden</span><span class="p">(</span><span class="s2">&quot;id&quot;</span><span class="p">));</span>
        <span class="p">}</span>

        <span class="nv">$name</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Text</span><span class="p">(</span><span class="s2">&quot;name&quot;</span><span class="p">);</span>
        <span class="nv">$name</span><span class="o">-&gt;</span><span class="na">setLabel</span><span class="p">(</span><span class="s2">&quot;Name&quot;</span><span class="p">);</span>
        <span class="nv">$name</span><span class="o">-&gt;</span><span class="na">setFilters</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;striptags&#39;</span><span class="p">,</span> <span class="s1">&#39;string&#39;</span><span class="p">));</span>
        <span class="nv">$name</span><span class="o">-&gt;</span><span class="na">addValidators</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
            <span class="k">new</span> <span class="nx">PresenceOf</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
                <span class="s1">&#39;message&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Name is required&#39;</span>
            <span class="p">))</span>
        <span class="p">));</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$name</span><span class="p">);</span>

        <span class="nv">$type</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Select</span><span class="p">(</span><span class="s1">&#39;profilesId&#39;</span><span class="p">,</span> <span class="nx">ProductTypes</span><span class="o">::</span><span class="na">find</span><span class="p">(),</span> <span class="k">array</span><span class="p">(</span>
            <span class="s1">&#39;using&#39;</span>      <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="s1">&#39;name&#39;</span><span class="p">),</span>
            <span class="s1">&#39;useEmpty&#39;</span>   <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span>
            <span class="s1">&#39;emptyText&#39;</span>  <span class="o">=&gt;</span> <span class="s1">&#39;...&#39;</span><span class="p">,</span>
            <span class="s1">&#39;emptyValue&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;&#39;</span>
        <span class="p">));</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$type</span><span class="p">);</span>

        <span class="nv">$price</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Text</span><span class="p">(</span><span class="s2">&quot;price&quot;</span><span class="p">);</span>
        <span class="nv">$price</span><span class="o">-&gt;</span><span class="na">setLabel</span><span class="p">(</span><span class="s2">&quot;Price&quot;</span><span class="p">);</span>
        <span class="nv">$price</span><span class="o">-&gt;</span><span class="na">setFilters</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;float&#39;</span><span class="p">));</span>
        <span class="nv">$price</span><span class="o">-&gt;</span><span class="na">addValidators</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
            <span class="k">new</span> <span class="nx">PresenceOf</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
                <span class="s1">&#39;message&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Price is required&#39;</span>
            <span class="p">)),</span>
            <span class="k">new</span> <span class="nx">Numericality</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
                <span class="s1">&#39;message&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Price is required&#39;</span>
            <span class="p">))</span>
        <span class="p">));</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$price</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The form is declared using an object-oriented scheme based on the elements provided by the <a class="reference internal" href="forms.html"><em>forms</em></a> component.
Every element follows almost the same structure:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="c1">// Create the element</span>
<span class="nv">$name</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Text</span><span class="p">(</span><span class="s2">&quot;name&quot;</span><span class="p">);</span>

<span class="c1">// Set its label</span>
<span class="nv">$name</span><span class="o">-&gt;</span><span class="na">setLabel</span><span class="p">(</span><span class="s2">&quot;Name&quot;</span><span class="p">);</span>

<span class="c1">// Before validating the element apply these filters</span>
<span class="nv">$name</span><span class="o">-&gt;</span><span class="na">setFilters</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;striptags&#39;</span><span class="p">,</span> <span class="s1">&#39;string&#39;</span><span class="p">));</span>

<span class="c1">// Apply this validators</span>
<span class="nv">$name</span><span class="o">-&gt;</span><span class="na">addValidators</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
    <span class="k">new</span> <span class="nx">PresenceOf</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
        <span class="s1">&#39;message&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Name is required&#39;</span>
    <span class="p">))</span>
<span class="p">));</span>

<span class="c1">// Add the element to the form</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$name</span><span class="p">);</span>
</pre></div>
</div>
<p>Other elements are also used in this form:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="c1">// Add a hidden input to the form</span>
<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="k">new</span> <span class="nx">Hidden</span><span class="p">(</span><span class="s2">&quot;id&quot;</span><span class="p">));</span>

<span class="c1">// ...</span>

<span class="c1">// Add a HTML Select (list) to the form</span>
<span class="c1">// and fill it with data from &quot;product_types&quot;</span>
<span class="nv">$type</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Select</span><span class="p">(</span><span class="s1">&#39;profilesId&#39;</span><span class="p">,</span> <span class="nx">ProductTypes</span><span class="o">::</span><span class="na">find</span><span class="p">(),</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">&#39;using&#39;</span>      <span class="o">=&gt;</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="s1">&#39;name&#39;</span><span class="p">),</span>
    <span class="s1">&#39;useEmpty&#39;</span>   <span class="o">=&gt;</span> <span class="k">true</span><span class="p">,</span>
    <span class="s1">&#39;emptyText&#39;</span>  <span class="o">=&gt;</span> <span class="s1">&#39;...&#39;</span><span class="p">,</span>
    <span class="s1">&#39;emptyValue&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;&#39;</span>
<span class="p">));</span>
</pre></div>
</div>
<p>Note that ProductTypes::find() contains the data necessary to fill the SELECT tag using Phalcon\Tag::select.
Once the form is passed to the view, it can be rendered and presented to the user:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="cp">{{</span> <span class="nv">form</span><span class="o">(</span><span class="s2">&quot;products/search&quot;</span><span class="o">)</span> <span class="cp">}}</span>

<span class="nt">&lt;h2&gt;</span>Search products<span class="nt">&lt;/h2&gt;</span>

<span class="nt">&lt;fieldset&gt;</span>

    <span class="cp">{%</span> <span class="k">for</span> <span class="nv">element</span> <span class="k">in</span> <span class="nv">form</span> <span class="cp">%}</span>
        <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;control-group&quot;</span><span class="nt">&gt;</span>
            <span class="cp">{{</span> <span class="nv">element.label</span><span class="o">([</span><span class="s1">&#39;class&#39;</span><span class="o">:</span> <span class="s1">&#39;control-label&#39;</span><span class="o">])</span> <span class="cp">}}</span>
            <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;controls&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">element</span> <span class="cp">}}</span><span class="nt">&lt;/div&gt;</span>
        <span class="nt">&lt;/div&gt;</span>
    <span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>

    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;control-group&quot;</span><span class="nt">&gt;</span>
        <span class="cp">{{</span> <span class="nv">submit_button</span><span class="o">(</span><span class="s2">&quot;Search&quot;</span><span class="o">,</span> <span class="s2">&quot;class&quot;</span><span class="o">:</span> <span class="s2">&quot;btn btn-primary&quot;</span><span class="o">)</span> <span class="cp">}}</span>
    <span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;/fieldset&gt;</span>
</pre></div>
</div>
<p>This produces the following HTML:</p>
<div class="highlight-html"><div class="highlight"><pre><span class="nt">&lt;form</span> <span class="na">action=</span><span class="s">&quot;/invo/products/search&quot;</span> <span class="na">method=</span><span class="s">&quot;post&quot;</span><span class="nt">&gt;</span>

<span class="nt">&lt;h2&gt;</span>Search products<span class="nt">&lt;/h2&gt;</span>

<span class="nt">&lt;fieldset&gt;</span>

    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;control-group&quot;</span><span class="nt">&gt;</span>
        <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">&quot;id&quot;</span> <span class="na">class=</span><span class="s">&quot;control-label&quot;</span><span class="nt">&gt;</span>Id<span class="nt">&lt;/label&gt;</span>
        <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;controls&quot;</span><span class="nt">&gt;&lt;input</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="na">id=</span><span class="s">&quot;id&quot;</span> <span class="na">name=</span><span class="s">&quot;id&quot;</span> <span class="nt">/&gt;&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>

    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;control-group&quot;</span><span class="nt">&gt;</span>
        <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">&quot;name&quot;</span> <span class="na">class=</span><span class="s">&quot;control-label&quot;</span><span class="nt">&gt;</span>Name<span class="nt">&lt;/label&gt;</span>
        <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;controls&quot;</span><span class="nt">&gt;</span>
            <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="na">id=</span><span class="s">&quot;name&quot;</span> <span class="na">name=</span><span class="s">&quot;name&quot;</span> <span class="nt">/&gt;</span>
        <span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>

    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;control-group&quot;</span><span class="nt">&gt;</span>
        <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">&quot;profilesId&quot;</span> <span class="na">class=</span><span class="s">&quot;control-label&quot;</span><span class="nt">&gt;</span>profilesId<span class="nt">&lt;/label&gt;</span>
        <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;controls&quot;</span><span class="nt">&gt;</span>
            <span class="nt">&lt;select</span> <span class="na">id=</span><span class="s">&quot;profilesId&quot;</span> <span class="na">name=</span><span class="s">&quot;profilesId&quot;</span><span class="nt">&gt;</span>
                <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">&quot;&quot;</span><span class="nt">&gt;</span>...<span class="nt">&lt;/option&gt;</span>
                <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">&quot;1&quot;</span><span class="nt">&gt;</span>Vegetables<span class="nt">&lt;/option&gt;</span>
                <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">&quot;2&quot;</span><span class="nt">&gt;</span>Fruits<span class="nt">&lt;/option&gt;</span>
            <span class="nt">&lt;/select&gt;</span>
        <span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>

    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;control-group&quot;</span><span class="nt">&gt;</span>
        <span class="nt">&lt;label</span> <span class="na">for=</span><span class="s">&quot;price&quot;</span> <span class="na">class=</span><span class="s">&quot;control-label&quot;</span><span class="nt">&gt;</span>Price<span class="nt">&lt;/label&gt;</span>
        <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;controls&quot;</span><span class="nt">&gt;&lt;input</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="na">id=</span><span class="s">&quot;price&quot;</span> <span class="na">name=</span><span class="s">&quot;price&quot;</span> <span class="nt">/&gt;&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>

    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;control-group&quot;</span><span class="nt">&gt;</span>
        <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;submit&quot;</span> <span class="na">value=</span><span class="s">&quot;Search&quot;</span> <span class="na">class=</span><span class="s">&quot;btn btn-primary&quot;</span> <span class="nt">/&gt;</span>
    <span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;/fieldset&gt;</span>
</pre></div>
</div>
<p>When the form is submitted, the action &#8220;search&#8221; is executed in the controller performing the search
based on the data entered by the user.</p>
</div>
<div class="section" id="performing-a-search">
<h3>Performing a Search<a class="headerlink" href="#performing-a-search" title="永久链接至标题">¶</a></h3>
<p>The action &#8220;search&#8221; has a dual behavior. When accessed via POST, it performs a search based on the data sent from the
form. But when accessed via GET it moves the current page in the paginator. To differentiate one from another HTTP method,
we check it using the <a class="reference internal" href="request.html"><em>Request</em></a> component:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="sd">/**</span>
<span class="sd"> * Execute the &quot;search&quot; based on the criteria sent from the &quot;index&quot;</span>
<span class="sd"> * Returning a paginator for the results</span>
<span class="sd"> */</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">searchAction</span><span class="p">()</span>
<span class="p">{</span>

    <span class="k">if</span> <span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="o">-&gt;</span><span class="na">isPost</span><span class="p">())</span> <span class="p">{</span>
        <span class="c1">//create the query conditions</span>
    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
        <span class="c1">//paginate using the existing conditions</span>
    <span class="p">}</span>

    <span class="c1">//...</span>

<span class="p">}</span>
</pre></div>
</div>
<p>With the help of <a class="reference internal" href="../api/Phalcon_Mvc_Model_Criteria.html"><em>Phalcon\Mvc\Model\Criteria</em></a>, we can create the search
conditions intelligently based on the data types and values sent from the form:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="nv">$query</span> <span class="o">=</span> <span class="nx">Criteria</span><span class="o">::</span><span class="na">fromInput</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">di</span><span class="p">,</span> <span class="s2">&quot;Products&quot;</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="o">-&gt;</span><span class="na">getPost</span><span class="p">());</span>
</pre></div>
</div>
<p>This method verifies which values are different from &#8220;&#8221; (empty string) and null and takes them into account to create
the search criteria:</p>
<ul class="simple">
<li>If the field data type is text or similar (char, varchar, text, etc.) It uses an SQL &#8220;like&#8221; operator to filter the results.</li>
<li>If the data type is not text or similar, it&#8217;ll use the operator &#8220;=&#8221;.</li>
</ul>
<p>Additionally, &#8220;Criteria&#8221; ignores all the $_POST variables that do not match any field in the table.
Values are automatically escaped using &#8220;bound parameters&#8221;.</p>
<p>Now, we store the produced parameters in the controller&#8217;s session bag:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">persistent</span><span class="o">-&gt;</span><span class="na">searchParams</span> <span class="o">=</span> <span class="nv">$query</span><span class="o">-&gt;</span><span class="na">getParams</span><span class="p">();</span>
</pre></div>
</div>
<p>A session bag, is a special attribute in a controller that persists between requests using the session service.
When accessed, this attribute injects a <a class="reference internal" href="../api/Phalcon_Session_Bag.html"><em>Phalcon\Session\Bag</em></a> instance
that is independent in each controller.</p>
<p>Then, based on the built params we perform the query:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="nv">$products</span> <span class="o">=</span> <span class="nx">Products</span><span class="o">::</span><span class="na">find</span><span class="p">(</span><span class="nv">$parameters</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">count</span><span class="p">(</span><span class="nv">$products</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
    <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">notice</span><span class="p">(</span><span class="s2">&quot;The search did not found any products&quot;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s2">&quot;products/index&quot;</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>If the search doesn&#8217;t return any product, we forward the user to the index action again. Let&#8217;s pretend the
search returned results, then we create a paginator to navigate easily through them:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="k">use</span> <span class="nx">Phalcon\Paginator\Adapter\Model</span> <span class="k">as</span> <span class="nx">Paginator</span><span class="p">;</span>

<span class="c1">// ...</span>

<span class="nv">$paginator</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Paginator</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
    <span class="s2">&quot;data&quot;</span>  <span class="o">=&gt;</span> <span class="nv">$products</span><span class="p">,</span>    <span class="c1">// Data to paginate</span>
    <span class="s2">&quot;limit&quot;</span> <span class="o">=&gt;</span> <span class="mi">5</span><span class="p">,</span>            <span class="c1">// Rows per page</span>
    <span class="s2">&quot;page&quot;</span>  <span class="o">=&gt;</span> <span class="nv">$numberPage</span>   <span class="c1">// Active page</span>
<span class="p">));</span>

<span class="c1">// Get active page in the paginator</span>
<span class="nv">$page</span> <span class="o">=</span> <span class="nv">$paginator</span><span class="o">-&gt;</span><span class="na">getPaginate</span><span class="p">();</span>
</pre></div>
</div>
<p>Finally we pass the returned page to view:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">view</span><span class="o">-&gt;</span><span class="na">page</span> <span class="o">=</span> <span class="nv">$page</span><span class="p">;</span>
</pre></div>
</div>
<p>In the view (app/views/products/search.phtml), we traverse the results corresponding to the current page,
showing every row in the current page to the user:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">for</span> <span class="nv">product</span> <span class="k">in</span> <span class="nv">page.items</span> <span class="cp">%}</span>
  <span class="cp">{%</span> <span class="k">if</span> <span class="nb">loop</span><span class="nv">.first</span> <span class="cp">%}</span>
    <span class="nt">&lt;table&gt;</span>
      <span class="nt">&lt;thead&gt;</span>
        <span class="nt">&lt;tr&gt;</span>
          <span class="nt">&lt;th&gt;</span>Id<span class="nt">&lt;/th&gt;</span>
          <span class="nt">&lt;th&gt;</span>Product Type<span class="nt">&lt;/th&gt;</span>
          <span class="nt">&lt;th&gt;</span>Name<span class="nt">&lt;/th&gt;</span>
          <span class="nt">&lt;th&gt;</span>Price<span class="nt">&lt;/th&gt;</span>
          <span class="nt">&lt;th&gt;</span>Active<span class="nt">&lt;/th&gt;</span>
        <span class="nt">&lt;/tr&gt;</span>
      <span class="nt">&lt;/thead&gt;</span>
    <span class="nt">&lt;tbody&gt;</span>
  <span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
  <span class="nt">&lt;tr&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.id</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.getProductTypes</span><span class="o">()</span><span class="nv">.name</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.name</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="s2">&quot;%.2f&quot;</span><span class="o">|</span><span class="nf">format</span><span class="o">(</span><span class="nv">product.price</span><span class="o">)</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.getActiveDetail</span><span class="o">()</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td</span> <span class="na">width=</span><span class="s">&quot;7%&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">link_to</span><span class="o">(</span><span class="s2">&quot;products/edit/&quot;</span> <span class="o">~</span> <span class="nv">product.id</span><span class="o">,</span> <span class="s1">&#39;Edit&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td</span> <span class="na">width=</span><span class="s">&quot;7%&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">link_to</span><span class="o">(</span><span class="s2">&quot;products/delete/&quot;</span> <span class="o">~</span> <span class="nv">product.id</span><span class="o">,</span> <span class="s1">&#39;Delete&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
  <span class="nt">&lt;/tr&gt;</span>
  <span class="cp">{%</span> <span class="k">if</span> <span class="nb">loop</span><span class="nv">.last</span> <span class="cp">%}</span>
  <span class="nt">&lt;/tbody&gt;</span>
    <span class="nt">&lt;tbody&gt;</span>
      <span class="nt">&lt;tr&gt;</span>
        <span class="nt">&lt;td</span> <span class="na">colspan=</span><span class="s">&quot;7&quot;</span><span class="nt">&gt;</span>
          <span class="nt">&lt;div&gt;</span>
            <span class="cp">{{</span> <span class="nv">link_to</span><span class="o">(</span><span class="s2">&quot;products/search&quot;</span><span class="o">,</span> <span class="s1">&#39;First&#39;</span><span class="o">)</span> <span class="cp">}}</span>
            <span class="cp">{{</span> <span class="nv">link_to</span><span class="o">(</span><span class="s2">&quot;products/search?page=&quot;</span> <span class="o">~</span> <span class="nv">page.before</span><span class="o">,</span> <span class="s1">&#39;Previous&#39;</span><span class="o">)</span> <span class="cp">}}</span>
            <span class="cp">{{</span> <span class="nv">link_to</span><span class="o">(</span><span class="s2">&quot;products/search?page=&quot;</span> <span class="o">~</span> <span class="nv">page.next</span><span class="o">,</span> <span class="s1">&#39;Next&#39;</span><span class="o">)</span> <span class="cp">}}</span>
            <span class="cp">{{</span> <span class="nv">link_to</span><span class="o">(</span><span class="s2">&quot;products/search?page=&quot;</span> <span class="o">~</span> <span class="nv">page.last</span><span class="o">,</span> <span class="s1">&#39;Last&#39;</span><span class="o">)</span> <span class="cp">}}</span>
            <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">&quot;help-inline&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">page.current</span> <span class="cp">}}</span> of <span class="cp">{{</span> <span class="nv">page.total_pages</span> <span class="cp">}}</span><span class="nt">&lt;/span&gt;</span>
          <span class="nt">&lt;/div&gt;</span>
        <span class="nt">&lt;/td&gt;</span>
      <span class="nt">&lt;/tr&gt;</span>
    <span class="nt">&lt;/tbody&gt;</span>
  <span class="nt">&lt;/table&gt;</span>
  <span class="cp">{%</span> <span class="k">endif</span> <span class="cp">%}</span>
<span class="cp">{%</span> <span class="k">else</span> <span class="cp">%}</span>
  No products are recorded
<span class="cp">{%</span> <span class="k">endfor</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>There are many things in the above example that worth detailing. First of all, active items
in the current page are traversed using a Volt&#8217;s &#8216;for&#8217;. Volt provides a simpler syntax for a PHP &#8216;foreach&#8217;.</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="cp">{%</span> <span class="k">for</span> <span class="nv">product</span> <span class="k">in</span> <span class="nv">page.items</span> <span class="cp">%}</span>
</pre></div>
</div>
<p>Which in PHP is the same as:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span> <span class="k">foreach</span> <span class="p">(</span><span class="nv">$page</span><span class="o">-&gt;</span><span class="na">items</span> <span class="k">as</span> <span class="nv">$product</span><span class="p">)</span> <span class="p">{</span> <span class="cp">?&gt;</span><span class="x"></span>
</pre></div>
</div>
<p>The whole &#8216;for&#8217; block provides the following:</p>
<blockquote>
<div><dl class="docutils">
<dt>{% for product in page.items %}</dt>
<dd><dl class="first docutils">
<dt>{% if loop.first %}</dt>
<dd>Executed before the first product in the loop</dd>
<dt>{% endif %}</dt>
<dd>Executed for every product of page.items</dd>
<dt>{% if loop.last %}</dt>
<dd>Executed after the last product is loop</dd>
</dl>
<p class="last">{% endif %}</p>
</dd>
<dt>{% else %}</dt>
<dd>Executed if page.items does not have any products</dd>
</dl>
<p>{% endfor %}</p>
</div></blockquote>
<p>Now you can go back to the view and find out what every block is doing. Every field
in &#8220;product&#8221; is printed accordingly:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="nt">&lt;tr&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.id</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.productTypes.name</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.name</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="s2">&quot;%.2f&quot;</span><span class="o">|</span><span class="nf">format</span><span class="o">(</span><span class="nv">product.price</span><span class="o">)</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.getActiveDetail</span><span class="o">()</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td</span> <span class="na">width=</span><span class="s">&quot;7%&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">link_to</span><span class="o">(</span><span class="s2">&quot;products/edit/&quot;</span> <span class="o">~</span> <span class="nv">product.id</span><span class="o">,</span> <span class="s1">&#39;Edit&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
    <span class="nt">&lt;td</span> <span class="na">width=</span><span class="s">&quot;7%&quot;</span><span class="nt">&gt;</span><span class="cp">{{</span> <span class="nv">link_to</span><span class="o">(</span><span class="s2">&quot;products/delete/&quot;</span> <span class="o">~</span> <span class="nv">product.id</span><span class="o">,</span> <span class="s1">&#39;Delete&#39;</span><span class="o">)</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
  <span class="nt">&lt;/tr&gt;</span>
</pre></div>
</div>
<p>As we seen before using product.id is the same as in PHP as doing: $product-&gt;id,
we made the same with product.name and so on. Other fields are rendered differently,
for instance, let&#8217;s focus in product.productTypes.name. To understand this part,
we have to check the model Products (app/models/Products.php):</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="k">use</span> <span class="nx">Phalcon\Mvc\Model</span><span class="p">;</span>

<span class="sd">/**</span>
<span class="sd"> * Products</span>
<span class="sd"> */</span>
<span class="k">class</span> <span class="nc">Products</span> <span class="k">extends</span> <span class="nx">Model</span>
<span class="p">{</span>
    <span class="c1">// ...</span>

    <span class="sd">/**</span>
<span class="sd">     * Products initializer</span>
<span class="sd">     */</span>
    <span class="k">public</span> <span class="k">function</span> <span class="nf">initialize</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">belongsTo</span><span class="p">(</span><span class="s1">&#39;product_types_id&#39;</span><span class="p">,</span> <span class="s1">&#39;ProductTypes&#39;</span><span class="p">,</span> <span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
            <span class="s1">&#39;reusable&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span>
        <span class="p">));</span>
    <span class="p">}</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>A model, can have a method called &#8220;initialize&#8221;, this method is called once per request and it serves
the ORM to initialize a model. In this case, &#8220;Products&#8221; is initialized by defining that this model
has a one-to-many relationship to another model called &#8220;ProductTypes&#8221;.</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">belongsTo</span><span class="p">(</span><span class="s1">&#39;product_types_id&#39;</span><span class="p">,</span> <span class="s1">&#39;ProductTypes&#39;</span><span class="p">,</span> <span class="s1">&#39;id&#39;</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span>
    <span class="s1">&#39;reusable&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span>
<span class="p">));</span>
</pre></div>
</div>
<p>Which means, the local attribute &#8220;product_types_id&#8221; in &#8220;Products&#8221; has an one-to-many relation to
the model &#8220;ProductTypes&#8221; in its attribute &#8220;id&#8221;. By defining this relation we can access the name of
the product type by using:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="nv">product.productTypes.name</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
</pre></div>
</div>
<p>The field &#8220;price&#8221; is printed by its formatted using a Volt filter:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="nt">&lt;td&gt;</span><span class="cp">{{</span> <span class="s2">&quot;%.2f&quot;</span><span class="o">|</span><span class="nf">format</span><span class="o">(</span><span class="nv">product.price</span><span class="o">)</span> <span class="cp">}}</span><span class="nt">&lt;/td&gt;</span>
</pre></div>
</div>
<p>What in PHP would be:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span> <span class="k">echo</span> <span class="nb">sprintf</span><span class="p">(</span><span class="s2">&quot;%.2f&quot;</span><span class="p">,</span> <span class="nv">$product</span><span class="o">-&gt;</span><span class="na">price</span><span class="p">)</span> <span class="cp">?&gt;</span><span class="x"></span>
</pre></div>
</div>
<p>Printing whether the product is active or not uses a helper implemented in the model:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="x">&lt;td&gt;{{ product.getActiveDetail() }}&lt;/td&gt;</span>
</pre></div>
</div>
<p>This method is defined in the model:</p>
</div>
<div class="section" id="creating-and-updating-records">
<h3>Creating and Updating Records<a class="headerlink" href="#creating-and-updating-records" title="永久链接至标题">¶</a></h3>
<p>Now let&#8217;s see how the CRUD creates and updates records. From the &#8220;new&#8221; and &#8220;edit&#8221; views the data entered by the user
are sent to the actions &#8220;create&#8221; and &#8220;save&#8221; that perform actions of &#8220;creating&#8221; and &#8220;updating&#8221; products respectively.</p>
<p>In the creation case, we recover the data submitted and assign them to a new &#8220;products&#8221; instance:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="sd">/**</span>
<span class="sd"> * Creates a new product</span>
<span class="sd"> */</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">createAction</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="o">-&gt;</span><span class="na">isPost</span><span class="p">())</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s2">&quot;products/index&quot;</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nv">$form</span>    <span class="o">=</span> <span class="k">new</span> <span class="nx">ProductsForm</span><span class="p">;</span>
    <span class="nv">$product</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Products</span><span class="p">();</span>

    <span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Remember the filters we defined in the Products form? Data is filtered before being assigned to the object $product.
This filtering is optional, also the ORM escapes the input data and performs additional casting according to the column types:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="c1">// ...</span>

<span class="nv">$name</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Text</span><span class="p">(</span><span class="s2">&quot;name&quot;</span><span class="p">);</span>
<span class="nv">$name</span><span class="o">-&gt;</span><span class="na">setLabel</span><span class="p">(</span><span class="s2">&quot;Name&quot;</span><span class="p">);</span>

<span class="c1">// Filters for name</span>
<span class="nv">$name</span><span class="o">-&gt;</span><span class="na">setFilters</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">&#39;striptags&#39;</span><span class="p">,</span> <span class="s1">&#39;string&#39;</span><span class="p">));</span>

<span class="c1">// Validators for name</span>
<span class="nv">$name</span><span class="o">-&gt;</span><span class="na">addValidators</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
        <span class="k">new</span> <span class="nx">PresenceOf</span><span class="p">(</span><span class="k">array</span><span class="p">(</span>
            <span class="s1">&#39;message&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;Name is required&#39;</span>
        <span class="p">))</span>
<span class="p">));</span>

<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">add</span><span class="p">(</span><span class="nv">$name</span><span class="p">);</span>
</pre></div>
</div>
<p>When saving we&#8217;ll know whether the data conforms to the business rules and validations implemented
in the form ProductsForm (app/forms/ProductsForm.php):</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="c1">// ...</span>

<span class="nv">$form</span>    <span class="o">=</span> <span class="k">new</span> <span class="nx">ProductsForm</span><span class="p">;</span>
<span class="nv">$product</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Products</span><span class="p">();</span>

<span class="c1">// Validate the input</span>
<span class="nv">$data</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="o">-&gt;</span><span class="na">getPost</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$form</span><span class="o">-&gt;</span><span class="na">isValid</span><span class="p">(</span><span class="nv">$data</span><span class="p">,</span> <span class="nv">$product</span><span class="p">))</span> <span class="p">{</span>
    <span class="k">foreach</span> <span class="p">(</span><span class="nv">$form</span><span class="o">-&gt;</span><span class="na">getMessages</span><span class="p">()</span> <span class="k">as</span> <span class="nv">$message</span><span class="p">)</span> <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">error</span><span class="p">(</span><span class="nv">$message</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s1">&#39;products/new&#39;</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Finally, if the form does not return any validation message we can save the product instance:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="c1">// ...</span>

<span class="k">if</span> <span class="p">(</span><span class="nv">$product</span><span class="o">-&gt;</span><span class="na">save</span><span class="p">()</span> <span class="o">==</span> <span class="k">false</span><span class="p">)</span> <span class="p">{</span>
    <span class="k">foreach</span> <span class="p">(</span><span class="nv">$product</span><span class="o">-&gt;</span><span class="na">getMessages</span><span class="p">()</span> <span class="k">as</span> <span class="nv">$message</span><span class="p">)</span> <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">error</span><span class="p">(</span><span class="nv">$message</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s1">&#39;products/new&#39;</span><span class="p">);</span>
<span class="p">}</span>

<span class="nv">$form</span><span class="o">-&gt;</span><span class="na">clear</span><span class="p">();</span>

<span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">success</span><span class="p">(</span><span class="s2">&quot;Product was created successfully&quot;</span><span class="p">);</span>
<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s2">&quot;products/index&quot;</span><span class="p">);</span>
</pre></div>
</div>
<p>Now, in the case of product updating, first we must present to the user the data that is currently in the edited record:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="sd">/**</span>
<span class="sd"> * Edits a product based on its id</span>
<span class="sd"> */</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">editAction</span><span class="p">(</span><span class="nv">$id</span><span class="p">)</span>
<span class="p">{</span>

    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="o">-&gt;</span><span class="na">isPost</span><span class="p">())</span> <span class="p">{</span>

        <span class="nv">$product</span> <span class="o">=</span> <span class="nx">Products</span><span class="o">::</span><span class="na">findFirstById</span><span class="p">(</span><span class="nv">$id</span><span class="p">);</span>
        <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$product</span><span class="p">)</span> <span class="p">{</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">error</span><span class="p">(</span><span class="s2">&quot;Product was not found&quot;</span><span class="p">);</span>
            <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s2">&quot;products/index&quot;</span><span class="p">);</span>
        <span class="p">}</span>

        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">view</span><span class="o">-&gt;</span><span class="na">form</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ProductsForm</span><span class="p">(</span><span class="nv">$product</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">&#39;edit&#39;</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The data found is bound to the form passing the model as first parameter. Thanks to this,
the user can change any value and then sent it back to the database through to the &#8220;save&#8221; action:</p>
<div class="highlight-php"><div class="highlight"><pre><span class="cp">&lt;?php</span>

<span class="sd">/**</span>
<span class="sd"> * Saves current product in screen</span>
<span class="sd"> *</span>
<span class="sd"> * @param string $id</span>
<span class="sd"> */</span>
<span class="k">public</span> <span class="k">function</span> <span class="nf">saveAction</span><span class="p">()</span>
<span class="p">{</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="o">-&gt;</span><span class="na">isPost</span><span class="p">())</span> <span class="p">{</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s2">&quot;products/index&quot;</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nv">$id</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="o">-&gt;</span><span class="na">getPost</span><span class="p">(</span><span class="s2">&quot;id&quot;</span><span class="p">,</span> <span class="s2">&quot;int&quot;</span><span class="p">);</span>
    <span class="nv">$product</span> <span class="o">=</span> <span class="nx">Products</span><span class="o">::</span><span class="na">findFirstById</span><span class="p">(</span><span class="nv">$id</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$product</span><span class="p">)</span> <span class="p">{</span>
        <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">error</span><span class="p">(</span><span class="s2">&quot;Product does not exist&quot;</span><span class="p">);</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s2">&quot;products/index&quot;</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nv">$form</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ProductsForm</span><span class="p">;</span>

    <span class="nv">$data</span> <span class="o">=</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">request</span><span class="o">-&gt;</span><span class="na">getPost</span><span class="p">();</span>
    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$form</span><span class="o">-&gt;</span><span class="na">isValid</span><span class="p">(</span><span class="nv">$data</span><span class="p">,</span> <span class="nv">$product</span><span class="p">))</span> <span class="p">{</span>
        <span class="k">foreach</span> <span class="p">(</span><span class="nv">$form</span><span class="o">-&gt;</span><span class="na">getMessages</span><span class="p">()</span> <span class="k">as</span> <span class="nv">$message</span><span class="p">)</span> <span class="p">{</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">error</span><span class="p">(</span><span class="nv">$message</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s1">&#39;products/new&#39;</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="k">if</span> <span class="p">(</span><span class="nv">$product</span><span class="o">-&gt;</span><span class="na">save</span><span class="p">()</span> <span class="o">==</span> <span class="k">false</span><span class="p">)</span> <span class="p">{</span>
        <span class="k">foreach</span> <span class="p">(</span><span class="nv">$product</span><span class="o">-&gt;</span><span class="na">getMessages</span><span class="p">()</span> <span class="k">as</span> <span class="nv">$message</span><span class="p">)</span> <span class="p">{</span>
            <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">error</span><span class="p">(</span><span class="nv">$message</span><span class="p">);</span>
        <span class="p">}</span>
        <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s1">&#39;products/new&#39;</span><span class="p">);</span>
    <span class="p">}</span>

    <span class="nv">$form</span><span class="o">-&gt;</span><span class="na">clear</span><span class="p">();</span>

    <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">flash</span><span class="o">-&gt;</span><span class="na">success</span><span class="p">(</span><span class="s2">&quot;Product was updated successfully&quot;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">forward</span><span class="p">(</span><span class="s2">&quot;products/index&quot;</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>We have seen how Phalcon lets you create forms and bind data from a database in a structured way.
In next chapter, we will see how to add custom HTML elements like a menu.</p>
</div>
</div>
</div>


                    </div>
                  </div>
                </div>
            </div>
          </td>
        </tr>
      </table>
    <div class="related">
      <ul>
        <li class="right" >
          <a href="../genindex.html" title="总目录"
             >索引</a></li>
        <li class="right" >
          <a href="tutorial-invo-4.html" title="Tutorial 5: Customizing INVO"
             >下一页</a> |</li>
        <li class="right" >
          <a href="tutorial-invo-2.html" title="Tutorial 3: Securing INVO"
             >上一页</a> |</li> 
      </ul>
    </div>

      <div class="prefooter">
  <div class="container">
      <div class="row">
          <div class="col-sm-3 text-right">
              <span>Follow along:</span>
          </div>
          <div class="col-sm-6 text-center">
              <a href="https://twitter.com/phalconphp" alt="Twitter" class="btn-social btn-social-twitter"><i class="icon-twitter"></i></a>
              <a href="https://www.facebook.com/pages/Phalcon-Framework/134230726685897" alt="Facebook" class="btn-social btn-social-facebook"><i class="icon-facebook"></i></a>
              <a href="https://plus.google.com/102376109340560896457" alt="Google+" class="btn-social btn-social-googleplus"><i class="icon-googleplus"></i></a>
              <a href="https://github.com/phalcon/cphalcon" alt="Github" class="btn-social btn-social-github"><i class="icon-github"></i></a>
          </div>
          <div class="col-sm-3">
          </div>
      </div>
  </div>

</div>
<footer class="footer">
  <div class="container">
      <div class="row">
          <div class="col-xs-4 col-sm-3">
              <h4>Download</h4>
              <ul>
                  <li><a href="http://phalconphp.com/download">Installing Phalcon</a></li>
                  <li><a href="http://docs.phalconphp.com/en/latest/index.html" class="header-nav-link" target="_blank">Documentation</a></li>
                  <li><a href="http://api.phalconphp.com">API</a></li>
                  <li><a href="http://docs.phalconphp.com/en/latest/reference/tutorial.html">Tutorial</a></li>
                  <li><a href="http://docs.phalconphp.com/en/latest/reference/tutorial.html#sample-applications">Sample Applications</a></li>
              </ul>
          </div>
          <div class="col-xs-4 col-sm-3">
              <h4>Community</h4>
              <ul>
                  <li><a href="http://forum.phalconphp.com/" class="header-nav-link" target="_blank">Forum</a></li>
                  <li><a href="https://github.com/phalcon/cphalcon">GitHub</a></li>
                  <li><a href="https://github.com/phalcon/cphalcon/issues">Issue Tracker</a></li>
                  <li><a href="http://stackoverflow.com/questions/tagged/phalcon">Stack Overflow</a></li>
                  <li><a href="http://phalconphp.com/en/testimonials">Testimonials</a></li>
                  <li><a href="http://builtwith.phalconphp.com/">Built with Phalcon</a></li>
                  <li><a href="http://store.phalconphp.com/">Store</a></li>
              </ul>
          </div>
          <div class="col-xs-4 col-sm-2">
              <h4>About</h4>
              <ul>
                  <li><a class="link-black" href="http://blog.phalconphp.com/">Blog</a></li>
                  <li><a href="http://phalconphp.com/en/about">About</a></li>
                  <li><a href="http://phalconphp.com/en/team">Team</a></li>
                  <li><a href="http://phalconphp.com/en/roadmap">Roadmap</a></li>
                  <li><a href="http://phalconphp.com/en/donate">Donate</a></li>
                  <li><a href="http://phalconphp.com/en/consulting">Consulting</a></li>
                  <li><a href="http://phalconphp.com/en/hosting">Hosting</a></li>
              </ul>
          </div>
          <div id="license-spaccer" class="visible-xs"></div>
          <div id="license-wrapper" class="col-xs-12 col-sm-4">
              <p class="license">

                  Found a typo or an error? Want to improve this document? The documentation sources are available on <a href="http://github.com/phalcon/docs">Github</a><br>
                  Need support or have questions? Check our <a href="http://forum.phalconphp.com">Forum</a><br>
                  <br>

                  Phalcon Framework is released under the <a href="https://github.com/phalcon/cphalcon/blob/master/docs/LICENSE.md">new BSD license</a>.<br>
                  Except where otherwise noted, content on this site is licensed under the
                    <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 License.</a>

                <div class="design">
                  <span>Designed by:</span>

                  <a href="http://www.fog-city.net/" class="fogcity" target="_blank" title="Fog City Software"><span>Fog City Software</span></a>
              </div>
          </div>
      </div>
  </div>
</footer>

    </div>
    <script type="text/javascript">
    $(window).on("load", function(){
      var cx = '009733439235723428699:lh9ltjgvdz8';
      var gcse = document.createElement('script');
      gcse.type = 'text/javascript';
      gcse.async = true;
      gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//www.google.com/cse/cse.js?cx=' + cx;
      var s = document.getElementsByTagName('script')[0];
      s.parentNode.insertBefore(gcse, s);
    });
    </script>

  </body>
</html>